﻿using System;
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace UFrameWork
{
    /// <summary>
    /// 消息分发器
    /// </summary>
    public class UMsgDispatcher : MonoBehaviour
    {
        /// <summary>
        /// 消息队列结构
        /// </summary>
        private class Qmsg
        {
            public UNetClient client;
            public string msg;
        }

        private static UMsgDispatcher _instance;

        /// <summary>
        /// 消息分发队列
        /// </summary>
        private Queue<Qmsg> queue = new Queue<Qmsg>();

        /// <summary>
        /// 单例
        /// </summary>
        public static UMsgDispatcher Instance
        {
            get
            {
                if (_instance == null) Create();
                return _instance;
            }
        }

        void Awake()
        {
            if (_instance != null) Destroy(gameObject);
        }

        void Update()
        {
            Dispatch();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {

        }

        /// <summary>
        /// 创建UI消息分发对象
        /// </summary>
        private static void Create()
        {
            GameObject obj = new GameObject("UMsgDispathcher");
            DontDestroyOnLoad(obj);
            obj.hideFlags = HideFlags.HideInHierarchy;
            _instance = obj.AddComponent<UMsgDispatcher>();
        }

        /// <summary>
        /// 增加一条待分发的消息
        /// </summary>
        /// <param name="msg"></param>
        public static void Add(UNetClient client,string msg)
        {
            if (_instance == null) return;
            lock (_instance.queue)
            {
                _instance.queue.Enqueue(new Qmsg() { client = client,msg = msg});
            }
        }

        /// <summary>
        /// 分发消息
        /// </summary>
        private void Dispatch()
        {
            if (_instance == null) return;

            Qmsg qmsg = null;

            lock (_instance.queue)
            {
                if (queue.Count == 0) return;
                qmsg = queue.Dequeue();
            }

            UWork.Do(UEvent.MSG_DISPATCH,qmsg.client,qmsg.msg);
            try
            {
                JObject json     = JsonConvert.DeserializeObject<JObject>(qmsg.msg);
                string key       = json["key"].Value<string>();
                List<Type> types = UWork.GetMethodParamType(key);
                if (types == null) return;
                List<object> paramobjs = new List<object>();
                for (int i = 0; i < types.Count; i++)
                {
                    paramobjs.Add(json["data"][i].ToObject(types[i]));
                }
                UWork.Do(key, paramobjs.ToArray());
            }
            catch (Exception e)
            {
                UWork.Do(UEvent.MSG_DISPATCH_ERROR,qmsg.client,qmsg.msg, e);
                ULog.Error("UMsgDispatcher:" + qmsg.msg + "\r\n" + e);
            }
        }
    }
}